home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-10-04 | 32.3 KB | 1,183 lines | [TEXT/MMCC] |
- /*================================================================================
- DialogUtilities.c
-
- circa 1991 by Greg Anderson
- greggor@apple.com
-
- This file contains various dialog box utility routines
- ================================================================================*/
- #include "DialogUtilities.h"
-
- #include <Types.h>
- #include <Errors.h>
- #include <Memory.h>
- #include <Resources.h>
- #include <Quickdraw.h>
- #include <Controls.h>
- #include <Dialogs.h>
- #include <MixedMode.h>
-
- #if USESROUTINEDESCRIPTORS
- RoutineDescriptor gDrawDottedLineProcRD = BUILD_ROUTINE_DESCRIPTOR(uppUserItemProcInfo, DrawDottedLineProc);
- RoutineDescriptor gDrawFrameRectProcRD = BUILD_ROUTINE_DESCRIPTOR(uppUserItemProcInfo, DrawFrameRectProc);
- RoutineDescriptor gDrawDefaultProcRD = BUILD_ROUTINE_DESCRIPTOR(uppUserItemProcInfo, DrawDefaultProc);
- RoutineDescriptor gDrawActiveItemProcRD = BUILD_ROUTINE_DESCRIPTOR(uppUserItemProcInfo, DrawActiveItemProc);
- RoutineDescriptor gDrawGreyTransformProcRD = BUILD_ROUTINE_DESCRIPTOR(uppUserItemProcInfo, DrawGreyTransformProc);
- RoutineDescriptor gCutPasteFilterRD = BUILD_ROUTINE_DESCRIPTOR(uppModalFilterProcInfo, CutPasteFilter);
- #endif
-
- //----------------------------------------------------------------------------------------
- // SimpleBox:
- //
- // Display a dialog
- //----------------------------------------------------------------------------------------
- void SimpleBox(short id)
- {
- DialogPtr dlog;
- short itemHit;
-
- dlog = GetNewDialog( id, (Ptr)0L, (WindowPtr)-1L);
-
- if( dlog != nil )
- {
- SetPort( dlog );
- SelectWindow(dlog);
- InstallDefaultOutline( dlog, 1 );
- CenterAndShowDialog(dlog);
-
- //
- // Wait for user to click "Okay"
- //
- do
- {
- #if USESROUTINEDESCRIPTORS
- ModalDialog((ModalFilterUPP) &gCutPasteFilterRD, &itemHit);
- #else
- ModalDialog((ModalFilterUPP) CutPasteFilter, &itemHit);
- #endif
- } while( itemHit != 1 );
- DisposDialog(dlog);
- }
- else
- {
- DebugStr( "\pCouldn't show simple dialog" );
- }
- } // SimpleBox
-
- //----------------------------------------------------------------------------------------
- // MessageBox:
- //
- // Display a message
- //----------------------------------------------------------------------------------------
- void MessageBox(short id, Str255 pstr)
- {
- DialogPtr dlog;
- short itemHit;
-
- dlog = GetNewDialog( id, (Ptr)0L, (WindowPtr)-1L);
-
- if( dlog != nil )
- {
- SetPort( dlog );
- ParamText( pstr, nil, nil, nil );
- SelectWindow(dlog);
- InstallDefaultOutline( dlog, 1 );
- CenterAndShowDialog(dlog);
-
- //
- // Wait for user to click "Okay"
- //
- do
- {
- #if USESROUTINEDESCRIPTORS
- ModalDialog((ModalFilterUPP) &gCutPasteFilterRD, &itemHit);
- #else
- ModalDialog((ModalFilterUPP) CutPasteFilter, &itemHit);
- #endif
- } while( itemHit != 1 );
- DisposDialog(dlog);
- }
- else
- {
- DebugStr( pstr );
- }
- } // MessageBox
-
- //----------------------------------------------------------------------------------------
- // CenterAndShowDialog:
- //
- // Center the specified dialog box & show it
- //
- // This code centers the dialog box on the main monitor (the one
- // with the menu bar) such that 1/3rd of the empty space left on
- // that screen is above the dialog and 2/3rds of it is below the
- // dialog
- //
- // Note:
- //
- // This routine looks at MBarHeight to correctly calculate the
- // horizontal position of the dialog box. Accessing low memory
- // globals is generally an evil thing to do, but in this case
- // there is no good alternative.
- //----------------------------------------------------------------------------------------
- void CenterAndShowDialog(DialogPtr dlog)
- {
- short menuHeight;
- short dlogWidth;
- short dlogHeight;
- short scrnWidth;
- short scrnHeight;
- short newDlogX;
- short newDlogY;
-
- //
- // What is the height of the menu bar (in pixels)?
- //
- menuHeight = GetMBarHeight();
-
- //
- // Calculate the size of the dialog box and the main screen
- // (without the menu bar)
- //
- dlogWidth = (dlog->portRect.right - dlog->portRect.left);
- dlogHeight = (dlog->portRect.bottom - dlog->portRect.top);
- scrnWidth = (qd.screenBits.bounds.right - qd.screenBits.bounds.left);
- scrnHeight = (qd.screenBits.bounds.bottom - qd.screenBits.bounds.top) - menuHeight;
-
- //
- // Quick check: don't leave any empty space if the dialog is
- // too large to fit on the main screen. This sanity check
- // really should not be necessary, though, as all dialog boxes
- // should fit on 9" screens
- //
- if( dlogHeight > scrnHeight)
- dlogHeight = scrnHeight;
-
- //
- // Calculate the menu's new location
- //
- newDlogX = qd.screenBits.bounds.left + (scrnWidth - dlogWidth) / 2;
- newDlogY = qd.screenBits.bounds.top + menuHeight + (scrnHeight - dlogHeight) / 3;
-
- //
- // Move the dialog and show it
- //
- MoveWindow(dlog,newDlogX,newDlogY,false);
- ShowWindow(dlog);
- } // CenterAndShowDialog
-
- //----------------------------------------------------------------------------------------
- // AddNewUserItem:
- //
- // Creates a new useritem in the specified dialog box & returns
- // its item number
- //----------------------------------------------------------------------------------------
- short AddNewUserItem( DialogPtr dlog )
- {
- DialogPeek theDialog = (DialogPeek)dlog;
- short** itemHandle = (short**)theDialog->items;
- short nItems = **itemHandle + 1;
- short newItem = 0;
- DITLitem* ditlPtr;
- Size itemHandleSize;
-
- itemHandleSize = GetHandleSize( (Handle)itemHandle );
- SetHandleSize( (Handle)itemHandle, itemHandleSize + sizeof(DITLitem) );
- if( MemError() == noErr )
- {
- //
- // We dereference the (potentially) unlocked itemHandle
- // here; don't do any memory-moving calls until we've
- // initialized the new DITL item
- //
- ditlPtr = (DITLitem*) ( (*itemHandle) + (itemHandleSize / sizeof(short)) );
-
- //
- // Fill in the new fields
- //
- ditlPtr->placeholder = 0;
- ditlPtr->itemType = userItem;
- ditlPtr->extraLength = 0;
-
- //
- // Remember / record the new number of items
- //
- newItem = nItems + 1;
- **itemHandle = newItem - 1;
- }
-
- return newItem;
- } // AddNewUserItem
-
- //----------------------------------------------------------------------------------------
- // DrawDottedLineProc:
- //
- // Draw a dotted line; install as the draw proc for a user item.
- //----------------------------------------------------------------------------------------
- pascal void DrawDottedLineProc(DialogPtr dlog, short item)
- {
- short type;
- Handle itemHandle;
- Rect box;
- PenState saveState;
- Point lineStart;
- Point lineEnd;
-
- //
- // Save the drawing mode before doing anything with
- // the pen
- //
- GetPenState( &saveState );
-
- //
- // Get the bounding box of the userItem & set lineStart
- // to the upper left corner and lineEnd to the lower right
- // corner of the bounding rectangle
- //
- GetDItem(dlog, item, &type, (Handle*)&itemHandle, &box);
- lineStart.h = box.left;
- lineStart.v = box.top;
- lineEnd.h = box.right;
- lineEnd.v = box.bottom;
-
- //
- // The line is always drawn along the longer edge
- //
- if( (lineEnd.h - lineStart.h) > (lineEnd.v - lineStart.v) )
- lineEnd.v = lineStart.v;
- else
- lineEnd.h = lineStart.h;
-
- //
- // Set the pen mode and draw the line
- //
- PenNormal();
- PenPat(&qd.gray);
- MoveTo( lineStart.h, lineStart.v );
- LineTo( lineEnd.h, lineEnd.v );
-
- //
- // Restore the pen state
- //
- SetPenState( &saveState );
- } // DrawDottedLineProc
-
- //----------------------------------------------------------------------------------------
- // SetUserItemToDottedLine:
- //
- // Make the given userItem a dotted line
- //----------------------------------------------------------------------------------------
- void SetUserItemToDottedLine( DialogPtr dlog, short whichItem )
- {
- short type;
- Handle itemHandle;
- Rect box;
-
- GetDItem(dlog,whichItem,&type,&itemHandle,&box);
- #if USESROUTINEDESCRIPTORS
- SetDItem(dlog,whichItem,type,(Handle)&gDrawDottedLineProcRD,&box);
- #else
- SetDItem(dlog,whichItem,type,(Handle)DrawDottedLineProc,&box);
- #endif
- } // SetUserItemToDottedLine
-
- //----------------------------------------------------------------------------------------
- // DrawFrameRectProc:
- //
- // Draw a frame around the specified userItem
- //----------------------------------------------------------------------------------------
- pascal void DrawFrameRectProc(DialogPtr dlog, short item)
- {
- short type;
- Handle itemHandle;
- Rect box;
- PenState saveState;
-
- //
- // Save the drawing mode before doing anything with
- // the pen
- //
- GetPenState( &saveState );
-
- //
- // Get the bounding box of the userItem
- //
- GetDItem(dlog, item, &type, (Handle*)&itemHandle, &box);
-
- //
- // Set the pen mode and draw the box
- //
- PenNormal();
- FrameRect( &box );
-
- //
- // Restore the pen state
- //
- SetPenState( &saveState );
- } // DrawFrameRectProc
-
- //----------------------------------------------------------------------------------------
- // SetUserItemToFrameRect:
- //
- // Make the given user item a simple frame
- //----------------------------------------------------------------------------------------
- void SetUserItemToFrameRect( DialogPtr dlog, short whichItem )
- {
- short type;
- Handle itemHandle;
- Rect box;
-
- GetDItem(dlog,whichItem,&type,&itemHandle,&box);
- #if USESROUTINEDESCRIPTORS
- SetDItem(dlog,whichItem,type,(Handle)&gDrawFrameRectProcRD,&box);
- #else
- SetDItem(dlog,whichItem,type,(Handle)DrawFrameRectProc,&box);
- #endif
- } // SetUserItemToFrameRect
-
- //----------------------------------------------------------------------------------------
- // DrawDefaultProc:
- //
- // Draw the thick rounded rectangle around the default button
- //
- // This routine uses Keith Rollin's algorithm, as presented in the
- // USENET Guide to Programming the Macintosh. I have modified the
- // basic algorithm only slightly--I add two to the calculated
- // 'buttonOval' value. This gets better results, particularly for
- // buttons of the default size (18 points).
- //----------------------------------------------------------------------------------------
- pascal void DrawDefaultProc(DialogPtr dlog, short item)
- {
- short defaultButton;
-
- //
- // Don't call GetDItem if the default button # has a strange value
- //
- defaultButton = ((DialogPeek)dlog)->aDefItem;
- if( defaultButton > 0 )
- {
- short type;
- Handle userHandle;
- Rect outlineBox;
-
- //
- // Only draw the bold outline around the default button
- // if it really is a button
- //
- GetDItem(dlog, defaultButton, &type, &userHandle, &outlineBox);
- if( (type & (ctrlItem + btnCtrl)) == ctrlItem + btnCtrl )
- {
- PenState saveState;
- short buttonOval;
-
- GetPenState( &saveState );
- InsetRect(&outlineBox,-4,-4);
-
- //
- // We want to draw the thick line with a normal
- // pen pattern that is 3 pixels wide
- //
- PenNormal();
- PenSize(3,3);
- PenMode(srcCopy);
-
- //
- // If the button we are outlining is disabled,
- // draw the outline with a gray pattern.
- //
- if( !DialogItemEnabled(dlog, defaultButton ) )
- {
- PenPat(&qd.gray);
- }
-
- //
- // Calculate the curvature to use and draw the thick line
- //
- buttonOval = 2 + (outlineBox.bottom - outlineBox.top) / 2;
- FrameRoundRect(&outlineBox,buttonOval,buttonOval);
-
- SetPenState( &saveState );
- }
- }
- } // DrawDefaultProc
-
- //----------------------------------------------------------------------------------------
- // InstallDefaultOutline:
- //
- // This function creates a useritem around the default button &
- // installs a drawing proc that draws the default border around it.
- //
- // If you want a button other than button #1 to act as the default
- // button, don't forget to supply your own filterProc that
- // translates Return to the correct item number. If you use the
- // CutPasteFilter implemented in this file, Return and Enter will
- // be translated to be equivalent to clicking on the button that
- // has the default outline around it.
- //----------------------------------------------------------------------------------------
- short InstallDefaultOutline(DialogPtr dlog, short button)
- {
- short userItem;
- short type;
- Handle item;
- Rect box;
- Rect userBox;
-
- ((DialogPeek)dlog)->aDefItem = button;
- userItem = AddNewUserItem( dlog );
- if( userItem > 0 )
- {
- GetDItem(dlog, button, &type, &item, &box);
- InsetRect(&box,-4,-4);
- GetDItem(dlog, userItem, &type, &item, &userBox);
- #if USESROUTINEDESCRIPTORS
- SetDItem(dlog,userItem,type,(Handle)&gDrawDefaultProcRD,&userBox);
- #else
- SetDItem(dlog,userItem,type,(Handle)DrawDefaultProc,&userBox);
- #endif
- }
-
- return userItem;
- } // InstallDefaultOutline
-
- //----------------------------------------------------------------------------------------
- // DrawActiveItemProc:
- //
- // Draw the thick square rectangle around the dialog item that accepts
- // keyboard input (see the System 7 Chooser for an example).
- //----------------------------------------------------------------------------------------
- pascal void DrawActiveItemProc(DialogPtr dlog, short item)
- {
- short type;
- Handle itemHandle;
- Rect box;
- PenState saveState;
-
- GetPenState( &saveState );
- GetDItem(dlog, item, &type, &itemHandle, &box);
- PenNormal();
- PenSize(2,2);
- FrameRect(&box);
- SetPenState( &saveState );
- } // DrawActiveItemProc
-
- //----------------------------------------------------------------------------------------
- // InstallActiveItemOutline:
- //
- // This function creates a useritem around the specified button & installs
- // a drawing proc that draws the default border around it.
- //----------------------------------------------------------------------------------------
- short InstallActiveItemOutline(DialogPtr dlog, short button)
- {
- short userItem;
- short type;
- Handle item;
- Rect box;
- Rect userBox;
-
- userItem = AddNewUserItem( dlog );
- if( userItem > 0 )
- {
- GetDItem(dlog, button, &type, &item, &box);
- InsetRect(&box,-4,-4);
- GetDItem(dlog, userItem, &type, &item, &userBox);
- #if USESROUTINEDESCRIPTORS
- SetDItem(dlog,userItem,type,(Handle)&gDrawActiveItemProcRD,&userBox);
- #else
- SetDItem(dlog,userItem,type,(Handle)DrawActiveItemProc,&userBox);
- #endif
- }
-
- return userItem;
- } // InstallActiveItemOutline
-
- //----------------------------------------------------------------------------------------
- // DrawGreyTransformProc:
- //
- // Draw a grey transform to shade out a disabled control; this is most
- // useful in conjunction with editText items, which do not normally draw
- // with a disabled transform.
- //
- // This function ASSUMES that the item after it is the one it should
- // check for enabled/disabledness.
- //----------------------------------------------------------------------------------------
- pascal void DrawGreyTransformProc(DialogPtr dlog, short item)
- {
- PenState saveState;
- short userItem;
- short type;
- Handle itemHandle;
- Rect userBox;
-
- //
- // Assume that the item before us is the one
- // that we are obscuring; check it for being
- // disabled
- //
- GetDItem(dlog, item - 1, &type, &itemHandle, &userBox);
- if(type & itemDisable)
- {
- GetDItem(dlog, item, &type, &itemHandle, &userBox);
-
- GetPenState( &saveState );
- PenNormal();
- PenPat(&qd.gray);
- PenMode(srcBic);
- PaintRect(&userBox);
- SetPenState( &saveState );
- }
- } // DrawGreyTransformProc
-
- //----------------------------------------------------------------------------------------
- // InstallGreyTransform:
- //
- // Install 'DrawGreyTransformProc' around the specified user item.
- //----------------------------------------------------------------------------------------
- short InstallGreyTransform(DialogPtr dlog, short userItem)
- {
- short type;
- Handle item;
- Rect userBox;
-
-
- GetDItem(dlog, userItem, &type, &item, &userBox);
- #if USESROUTINEDESCRIPTORS
- SetDItem(dlog,userItem,type,(Handle)&gDrawGreyTransformProcRD,&userBox);
- #else
- SetDItem(dlog,userItem,type,(Handle)DrawGreyTransformProc,&userBox);
- #endif
-
- return userItem;
- } // InstallGreyTransform
-
- //----------------------------------------------------------------------------------------
- // MoveOutline:
- //
- // Move a userItem around the appropriate button.
- //
- // This function should be used in conjunction with
- // InstallDefaultOutline to move the default button indicator
- // from one button to another. If you are using the
- // CutPasteFilter with this routine, Return and Enter will
- // automatically be translated to the correct button
- //----------------------------------------------------------------------------------------
- void MoveOutline(DialogPtr dlog, short userItem, short button)
- {
- short type;
- Handle item;
- Rect newBox;
- Rect oldBox;
-
- GetDItem(dlog, ((DialogPeek)dlog)->aDefItem, &type, &item, &oldBox);
- InsetRect(&oldBox,-4,-4);
- GetDItem(dlog, button, &type, &item, &newBox);
- InsetRect(&newBox,-4,-4);
-
- //
- // Erase the old box & invalidate the old and new
- // locations to force a redraw
- //
- EraseRect( &oldBox );
- InvalRect( &oldBox );
- InvalRect( &newBox );
-
- //
- // Remember where the default button outline moved to
- //
- ((DialogPeek)dlog)->aDefItem = button;
- } // MoveOutline
-
- //----------------------------------------------------------------------------------------
- // MoveActiveIndicator:
- //
- // Move the active item indicator to another item.
- //
- // Note: This routine erases and redraws the active item.
- // It would be better to erase & invalidate, but that's
- // pretty slow.
- //----------------------------------------------------------------------------------------
- void MoveActiveIndicator(DialogPtr dlog, short userItem, short button)
- {
- short type;
- Handle item;
- Rect box;
- Rect userBox;
- RgnHandle badRgn;
- RgnHandle tmpRgn;
-
- GetDItem(dlog, button, &type, &item, &box);
- InsetRect(&box,-4,-4);
- GetDItem(dlog, userItem, &type, &item, &userBox);
- SetDItem(dlog, userItem, type, item, &box );
-
- //
- // Erase the old active item indicator
- //
- badRgn = NewRgn();
- tmpRgn = NewRgn();
- RectRgn( badRgn, &userBox );
- InsetRect( &userBox, 2, 2 );
- RectRgn( tmpRgn, &userBox );
- DiffRgn( badRgn, tmpRgn, badRgn );
- EraseRgn( badRgn );
- InvalRgn( badRgn );
- DisposeRgn( badRgn );
- DisposeRgn( tmpRgn );
-
- //
- // Draw the new one
- //
- DrawActiveItemProc( dlog, userItem );
- } // MoveActiveIndicator
-
- //----------------------------------------------------------------------------------------
- // MoveDItem:
- //
- // Move a Dialog Item.
- //
- // This is not _quite_ as easy as it sounds, because if the item
- // is a control (such as a check box or radio button), MoveControl
- // must also be called.
- //
- // NOTE: This routine doesn't quite work, because it does not
- // erase or redraw the item that moved unless it is
- // a control. Tsk tsk.
- //----------------------------------------------------------------------------------------
- void MoveDItem( DialogPtr dlog, short itemNumber, short h, short v )
- {
- Handle itemHandle;
- short itemType;
- Rect box;
-
- //
- // Get some useful information about the DItem to move
- //
- GetDItem( dlog, itemNumber, &itemType, (Handle*)&itemHandle, &box );
-
- //
- // Move the bounding box to the correct location
- //
- box.bottom += (v - box.top);
- box.right += (h - box.left);
- box.top = v;
- box.left = h;
-
- //
- // Set the bounding box of the item to move
- //
- SetDItem( dlog, itemNumber, itemType, (Handle)itemHandle, &box );
-
- //
- // If the item is a control, call MoveControl
- //
- if( (itemType & ctrlItem) != 0 )
- {
- MoveControl( (ControlHandle)itemHandle, h, v );
- }
- } // MoveDItem
-
- //----------------------------------------------------------------------------------------
- // SetItemHandle:
- //
- // Set the item handle of a dialog item (particularly useful for
- // useritems)
- //----------------------------------------------------------------------------------------
- void SetItemHandle( DialogPtr dlog, short whichItem, Handle newItem )
- {
- short type;
- Handle itemHandle;
- Rect box;
-
- GetDItem(dlog,whichItem,&type,&itemHandle,&box);
- SetDItem(dlog,whichItem,type,newItem,&box);
- } // SetItemHandle
-
- //----------------------------------------------------------------------------------------
- // GetItemPoint:
- //
- // Returns the location of a given dialog item
- //----------------------------------------------------------------------------------------
- Point GetItemPoint( DialogPtr dlog, short itemNum )
- {
- Point loc;
- short type;
- Handle item;
- Rect box;
-
- GetDItem(dlog,itemNum, &type, &item, &box);
- loc.h = box.left;
- loc.v = box.top;
- return( loc );
- } // GetItemPoint
-
- //----------------------------------------------------------------------------------------
- // DialogItemEnabled:
- //
- // This routine is used by DrawDefaultProc and CutPasteFilter
- // to determine if the default button is enabled
- //----------------------------------------------------------------------------------------
- Boolean DialogItemEnabled(DialogPtr dlog, short item)
- {
- ControlHandle buttonHandle = nil;
- Rect buttonBox;
- short type;
-
- GetDItem(dlog, item, &type, (Handle*)&buttonHandle, &buttonBox);
- return ((type & itemDisable) == false);
- } // DialogItemEnabled
-
- //----------------------------------------------------------------------------------------
- // SetDialogItemDisableBit:
- //
- // Set or clear the 'itemDisable' bit of the dialog item
- //----------------------------------------------------------------------------------------
- void SetDialogItemDisableBit(DialogPtr dlog, short item, Boolean enable)
- {
- Handle itemHandle;
- short itemType;
- Rect box;
-
- GetDItem(dlog,item,&itemType,&itemHandle,&box);
- itemType = (itemType & ~itemDisable) + (enable ? 0 : itemDisable);
- SetDItem(dlog,item,itemType,itemHandle,&box);
- } // SetDialogItemDisableBit
-
- //----------------------------------------------------------------------------------------
- // EnableButton:
- //
- // This simple routine will enable or disable a button
- //----------------------------------------------------------------------------------------
- void EnableButton(DialogPtr dlog, short button,Boolean enable)
- {
- ControlHandle buttonHandle;
- short type;
- Rect box;
-
- SetDialogItemDisableBit(dlog, button, enable);
- GetDItem(dlog,button,&type,(Handle*)&buttonHandle,&box);
- HiliteControl(buttonHandle, enable ? 0 : 255);
-
- //
- // Special checking: are we enabling/disabling the
- // default button? If so, invalidate the area around
- // the button so the default outline will redraw
- //
- if(button == ((DialogPeek)dlog)->aDefItem)
- {
- InsetRect(&box, -6, -6);
- InvalRect(&box);
- }
- } // EnableButton
-
- //----------------------------------------------------------------------------------------
- // EnabledTEItemsExist:
- //
- // Return true if there is at least one enabled TE item
- //----------------------------------------------------------------------------------------
- Boolean EnabledTEItemsExist(DialogPtr dlog)
- {
- Boolean enabledTEExists = false;
- short i;
-
- for(i=1; i < (**((short**)(((DialogPeek)dlog)->items)) + 1); ++i)
- {
- Handle itemHandle;
- short itemType;
- Rect box;
-
- GetDItem(dlog,i,&itemType,&itemHandle,&box);
- if(((itemType & itemDisable) == 0) && ((itemType & editText) == editText))
- enabledTEExists = true;
- }
-
- return enabledTEExists;
- }
-
- //----------------------------------------------------------------------------------------
- // FindNextEnabledTEItem:
- //
- // Return the item # of the next enabled EditText item.
- //----------------------------------------------------------------------------------------
- short FindNextEnabledTEItem(DialogPtr dlog, short item)
- {
- short searchFrom = item + 1;
- short terminate = 0;
- short itemFound = 0;
-
- //
- // Look at every item in the list except for 'item'
- //
- while((searchFrom != item) && (searchFrom != terminate))
- {
- Handle itemHandle;
- short itemType;
- Rect box;
-
- //
- // When we get to the end, wrap around. Set 'terminate'
- // just in case 'item' has a bogus value
- //
- if(searchFrom > (**((short**)(((DialogPeek)dlog)->items)) + 1))
- {
- terminate = searchFrom;
- searchFrom = 1;
- }
-
- //
- // Is this item an enabled textEdit item?
- //
- GetDItem(dlog,searchFrom,&itemType,&itemHandle,&box);
- if(((itemType & itemDisable) == 0) && ((itemType & editText) == editText))
- {
- itemFound = searchFrom;
- break;
- }
- ++searchFrom;
- }
-
- return itemFound;
- }
-
- //----------------------------------------------------------------------------------------
- // TabToNextEnabledTEItem:
- //
- // The dialog manager does not respect disabled TE items, so we need to have our
- // own method of skipping to the next item when tab is pressed.
- //----------------------------------------------------------------------------------------
- void TabToNextEnabledTEItem(DialogPtr dlog)
- {
- short itemToTabTo = FindNextEnabledTEItem(dlog, ((DialogPeek)dlog)->editField + 1);
- if(itemToTabTo > 0)
- {
- SelIText(dlog, itemToTabTo, 0, 32767);
- }
- }
-
- //----------------------------------------------------------------------------------------
- // EnableTEItem:
- //
- // I wish this worked without extra support, but the dialog manager does not
- // respect disabled editText items. We have some convoluted code here that works
- // in conjunction with the modless dialog handler code in the Window handler that
- // allows us to disable editText items.
- //----------------------------------------------------------------------------------------
- void EnableTEItem(DialogPtr dlog, short item, Boolean enable)
- {
- Handle itemHandle;
- short itemType;
- Rect box;
-
- //
- // First check to see if the TE item is going from
- // enabled to disabled
- //
- GetDItem(dlog,item,&itemType,&itemHandle,&box);
- if((enable == false) && ((itemType & itemDisable) == 0))
- {
- //
- // Is this item the active TE item?
- //
- if(((DialogPeek)dlog)->editField == item - 1)
- {
- //
- // Find an enabled editText item
- //
- short anEnabledItem = FindNextEnabledTEItem(dlog, item);
- if(anEnabledItem == 0)
- {
- //
- // Time to disable the last TE item
- //
- SelIText(dlog, item, 0, 0);
- TEDeactivate(((DialogPeek)dlog)->textH);
- }
- else
- {
- //
- // I hope that this will activate the item whose
- // text is being selected, and deactivate 'item'
- //
- SelIText(dlog, anEnabledItem, 0, 32767);
- }
- }
- }
-
- //
- // Invalidate the area around the TE item in case
- // InstallGreyTransform was called on a userItem
- // around it.
- //
- InsetRect(&box, -6, -6);
- InvalRect(&box);
- SetDialogItemDisableBit(dlog, item, enable);
-
- //
- // We also have some work to do when enabling the first
- // TE item (since we called TEDeactivate when we disable
- // the last item, we'd better call TEActivate when we
- // enable it)
- //
- if((enable == true) && ((itemType & itemDisable) != 0))
- {
- //
- // If there is an enabled item somewhere, we don't
- // have to worry about calling TEActivate because
- // we did not call TEDeactivate.
- //
- if(FindNextEnabledTEItem(dlog, item) == 0)
- {
- //
- // Fortunately, we don't need to worry about
- // the fact that we may have disabled a
- // "different" editText item, because there
- // is only one TEHandle that is shared among
- // all editable items.
- //
- TEActivate(((DialogPeek)dlog)->textH);
- SelIText(dlog, item, 0, 32767);
- }
- }
- } // EnableTEItem
-
- //----------------------------------------------------------------------------------------
- // GetCheckboxState:
- //
- // Returns true of the checkbox is checked
- //----------------------------------------------------------------------------------------
- Boolean GetCheckboxState(DialogPtr dlog, short checkbox)
- {
- Boolean state = false;
- short itemType;
- ControlHandle checkboxControl;
- Rect box;
-
- GetDItem(dlog, checkbox, &itemType, (Handle*)&checkboxControl, &box);
- if((itemType & (chkCtrl + ctrlItem)) == chkCtrl + ctrlItem)
- {
- state = GetCtlValue(checkboxControl);
- }
-
- return state;
- } // GetCheckboxState
-
- //----------------------------------------------------------------------------------------
- // SetCheckboxState:
- //
- // Check or uncheck a button
- //----------------------------------------------------------------------------------------
- void SetCheckboxState(DialogPtr dlog, short checkbox, Boolean check)
- {
- short itemType;
- ControlHandle checkboxControl;
- Rect box;
-
- GetDItem(dlog, checkbox, &itemType, (Handle*)&checkboxControl, &box);
- if((itemType & (chkCtrl + ctrlItem)) == chkCtrl + ctrlItem)
- {
- SetCtlValue(checkboxControl, check);
- }
- } // SetCheckboxState
-
- //----------------------------------------------------------------------------------------
- // ToggleCheckboxState:
- //
- // Reverse the state of a checkbox
- //----------------------------------------------------------------------------------------
- void ToggleCheckboxState(DialogPtr dlog, short checkbox)
- {
- SetCheckboxState(dlog, checkbox, !GetCheckboxState(dlog, checkbox));
- } // ToggleCheckboxState
-
- //----------------------------------------------------------------------------------------
- // FlashDlogItem:
- //
- // Momentarily hilite a dialog button
- //----------------------------------------------------------------------------------------
- void FlashDlogItem( DialogPtr dlog, short itemNum )
- {
- Handle itemHandle;
- short itemType;
- Rect iRect;
- long ticky;
-
- GetDItem(dlog,itemNum,&itemType,&itemHandle,&iRect);
- HiliteControl((ControlHandle)itemHandle,1);
- Draw1Control((ControlHandle)itemHandle);
- ticky = TickCount() + 10;
- do {} while( ticky > TickCount() );
- HiliteControl((ControlHandle)itemHandle,0);
- Draw1Control((ControlHandle)itemHandle);
- } // FlashDlogItem
-
- //----------------------------------------------------------------------------------------
- // CutPasteFilter:
- //
- // This filter, when passed to ModalDialog, will allow the user to
- // cut, copy and paste by pressing command-X, command-C or command-V,
- // respectively. It also checks if the cursor is over an editText
- // item, and if so, the cursor is changed into an IBeam.
- //
- // This procedure may be used as the filterProc of any dialog that
- // uses ModelDialog(). Note that this filter calls FlashDlogItem(),
- // above. In all other respects, it is completely self-contained.
- //
- // This routine always translates command-. to button #2.
- // Your dialog box should have button #2 set up as a
- // 'Cancel' button if you use this routine.
- //----------------------------------------------------------------------------------------
- pascal Boolean CutPasteFilter( DialogPtr dlog, EventRecord* event, short* item )
- {
- DialogRecord *dp = (DialogRecord *)dlog;
- TEHandle te;
- Str255 Pstr;
- long num;
- char key;
- char code;
- short itemType = statText;
- short itemNum;
- Handle itemHandle;
- Point mouse;
- Rect tRect;
-
- te = dp->textH;
-
- //
- // Adjust the cursor to an iBeam or Arrow as appropriate
- //
- GetMouse( &mouse );
- itemNum = FindDItem(dlog,mouse) + 1;
- if( itemNum > 0 )
- GetDItem(dlog,itemNum,&itemType,&itemHandle,&tRect);
- SetCursor( (itemType == editText) ? *GetCursor(iBeamCursor) : &qd.arrow);
-
- //
- // If the event is an update event, check to see
- // if it is for this dialog or for some other window
- //
- if( (event->what == updateEvt) )
- {
- //
- // If the update event is for this dialog box,
- // then draw the default button
- //
- if( StripAddress((DialogPtr)event->message) == StripAddress(dlog) )
- {
- //
- // The 'item' parameter is ignored, but we
- // don't have any better value to pass to
- // it than the item # of the default button
- //
- DrawDefaultProc(dlog, ((DialogPeek)dlog)->aDefItem );
- }
- }
-
- //
- // Is the event a key-down event?
- //
- if( (event->what == keyDown) || (event->what == autoKey) )
- {
- key = (event->message & charCodeMask);
- code = (event->message & keyCodeMask) >> 8;
-
- //
- // If F2, F3 or F4 (cut, copy or paste) are pressed,
- // forge a Command-X, C or V and handle the appropriate
- // command below.
- //
- switch( code )
- {
- case 120:
- {
- event->modifiers |= cmdKey;
- key = 'x';
- break;
- }
-
- case 99:
- {
- event->modifiers |= cmdKey;
- key = 'c';
- break;
- }
-
- case 118:
- {
- event->modifiers |= cmdKey;
- key = 'v';
- break;
- }
- }
-
- //
- // Is the command key down?
- //
- if( event->modifiers & cmdKey )
- {
- switch( key )
- {
- //
- // Command-X, C and V are cut, copy and paste.
- //
- case 'x':
- case 'c':
- {
- ZeroScrap();
- if( key == 'x' )
- DlgCut( dlog );
- else
- DlgCopy( dlog );
- if( TEToScrap() != noErr )
- SysBeep(120);
- return true;
- }
-
- case 'v':
- {
- if( TEFromScrap() == noErr )
- DlgPaste( dlog );
- else
- SysBeep(120);
- return true;
- }
-
- //
- // Command-. cancels
- //
- case '.':
- {
- *item = 2;
- FlashDlogItem( dlog, *item );
- return true;
- }
- }
-
- //
- // All other command-key combinations do nothing
- //
- event->what = nullEvent;
- return false;
- }
-
- //
- // If RETURN or ENTER was pressed, exit with
- // itemHit = ((DialogPeek)dlog)->aDefItem--but only if the
- // default button is enabled.
- //
- if( ((key == 13) || (key == 3)) && DialogItemEnabled(dlog,((DialogPeek)dlog)->aDefItem) )
- {
- *item = ((DialogPeek)dlog)->aDefItem;
- FlashDlogItem( dlog, *item );
- return true;
- }
-
- //
- // Swallow non-printing characters
- //
- if( (key < ' ') && (key != 8) && (key != 9) )
- {
- event->what = nullEvent;
- return false;
- }
- }
- return false;
- } // CutPasteFilter
-